﻿using System;
using System.Collections.Generic;

namespace O2DESNet {
	public class Event : IDisposable {
		public class EventPool {
			private static int poolSize = 100;
			private List<Event> events = new List<Event>(poolSize + 10);

			public void Die(Event eve) {
				if (events.Count < poolSize) {
					events.Add(eve);
				}
			}

			public Event CreateEvent(Sandbox owner, Action action, DateTime scheduledTime, string tag = null) {
				if (events.Count > 0) {
					Event eve = events[events.Count - 1];
					events.RemoveAt(events.Count - 1);
					eve.Index = _count++;
					eve.Owner = owner;
					eve.Action = action;
					eve.ScheduledTime = scheduledTime;
					eve.Tag = tag;
					return eve;
				}

				return new Event(owner, action, scheduledTime, tag);
			}
		}
		
		private static int _count = 0;
		internal int Index { get; private set; } = _count++;
		internal string Tag { get; private set; }
		internal Sandbox Owner { get; private set; }
		internal DateTime ScheduledTime { get; private set; }
		internal Action Action { get; private set; }

		internal Event Create(Sandbox owner, Action action, DateTime scheduledTime, string tag = null) {
			return new Event(owner, action, scheduledTime, tag);
		}

		internal Event(Sandbox owner, Action action, DateTime scheduledTime, string tag = null) {
			Owner = owner;
			Action = action;
			ScheduledTime = scheduledTime;
			Tag = tag;
		}

		internal void Invoke() {
			Action.Invoke();
		}

		public override string ToString() {
			return string.Format("{0}#{1}", Tag, Index);
		}

		public void Dispose() {
		}
	}

	internal sealed class EventComparer : IComparer<Event> {
		private static readonly EventComparer _instance = new EventComparer();

		private EventComparer() {
		}

		public static EventComparer Instance {
			get { return _instance; }
		}

		public int Compare(Event x, Event y) {
			int compare = x.ScheduledTime.CompareTo(y.ScheduledTime);
			if (compare == 0) return x.Index.CompareTo(y.Index);
			return compare;
		}
	}
}